package net.siufung.simple.security.controller;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.model.consts.Constants;
import net.siufung.core.result.Result;
import net.siufung.core.utils.StringPool;
import net.siufung.market.base.menu.controller.model.vo.MenuTreeNode;
import net.siufung.security.api.AuthUtil;
import net.siufung.security.base.service.ICurrentUserService;
import net.siufung.simple.security.sevice.ISecurityCacheService;
import net.siufung.simple.security.sevice.ISecurityService;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 会话管理
 * @author 陈建峰
 * @since 2022/7/7 10:00 下午
 */
@SuppressWarnings("deprecation")
@Slf4j
@RestController
@AllArgsConstructor
@Api(tags = "会话管理")
@RequestMapping(value = "/session")
public class SecurityController {

    private final ISecurityService securityService;
    private final ICurrentUserService currentUserService;
    private final ISecurityCacheService securityCacheService;
    private final TokenStore tokenStore;

    /**
     * 获得当前授权用户
     * @return Result<Map<String, Object>>
     */
    @ApiOperation(value = "获得当前用户信息")
    @GetMapping("/current")
    public Result<Map<String, Object>> current() {
        Map<String, Object> sessionMap = Maps.newHashMap();
        sessionMap.put("user", AuthUtil.getCurrentUser());
        sessionMap.put("permissions", this.permissions().getData());
        sessionMap.put("menus", this.currentMenuTree(1).getData());
        sessionMap.put("roles", Collections.singletonList("admin"));
        return Result.ok(sessionMap);
    }

    /**
     * 获得权限标识列表
     * @return 权限字符串列表
     */
    @ApiOperation(value = "获得权限标识", notes = "获得用户有权限的权限标识")
    @PostMapping(value = "/currentAuthorities")
    public Result<List<String>> permissions() {
        return Result.ok(currentUserService.getAuthorities());
    }

    /**
     * 获得权限菜单
     * @param parentId 父级ID
     * @return 菜单树
     */
    @ApiOperation(value = "获得权限菜单")
    @PostMapping(value = "/currentMenuTree")
    public Result<List<Tree<Integer>>> currentMenuTree(
            @RequestParam(value = "parentId", required = false) Integer parentId) {
        if (ObjectUtil.isNull(parentId)) {
            parentId = Integer.valueOf(StringPool.ZERO);
        }
        List<MenuTreeNode> menuTreeNodeList = securityService.getCurrentMenuTree();
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        List<Tree<Integer>> menuTreeList = TreeUtil.build(
                menuTreeNodeList, parentId, treeNodeConfig, (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setWeight(treeNode.getWeight());
                    tree.setName(treeNode.getName());
                    tree.putExtra("code", treeNode.getCode());
                    tree.putExtra("type", treeNode.getType());
                    tree.putExtra("path", treeNode.getRouter());
                    tree.putExtra("router", treeNode.getRouter());
                    tree.putExtra("authority", treeNode.getAuthority());
                    tree.putExtra("keepAlive", treeNode.getKeepAlive());
                    tree.putExtra("icon", treeNode.getIcon());
                    tree.putExtra("level", treeNode.getLevel());
                });
        return Result.ok(menuTreeList);
    }

    /**
     * 退出
     * @param headers 请求头
     */
    @ApiOperation(value = "退出系统")
    @PostMapping("/logout")
    public Result<Void> logout(@RequestHeader HttpHeaders headers) {
        String token = headers.getFirst(HttpHeaders.AUTHORIZATION);
        token = StrUtil.subSuf(token, Constants.BEARER.length());
        OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token);
        OAuth2RefreshToken refreshToken;
        if (existingAccessToken != null) {
            if (existingAccessToken.getRefreshToken() != null) {
                refreshToken = existingAccessToken.getRefreshToken();
                tokenStore.removeRefreshToken(refreshToken);
            }
            tokenStore.removeAccessToken(existingAccessToken);
        }
        //清楚权限菜单等缓存
        securityCacheService.clearAuthCaches(AuthUtil.getUserId());
        return Result.ok();
    }

}
